<?php

/*
	This file is part of Mandragon.

    Mandragon is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Mandragon is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Mandragon.  If not, see <http://www.gnu.org/licenses/>.
*/

class AccessPage {

	private $alerter;
	private $access;
	private $creator;
	private $db_access;
	private $toolbox;
	private $error_nav;
	
	public function __construct() {
		$this->alerter = new Alerter();
		$this->access = new AccessManager();
		$this->creator = new FormCreator();
		$this->db_access = new DbAccessor();
		$this->toolbox = new Toolbox();
		$this->error_nav = new ErrorNavigation();
	}

	public function set_access_manager($access) {
		$this->access = $access;
	}

	public function set_alerter($alerter) {
		$this->alerter = $alerter;
	}

	public function set_db_accessor($db_access) {
		$this->db_access = $db_access;
	}

	public function set_toolbox($toolbox) {
		$this->toolbox = $toolbox;
	}

	public function set_error_navigation($error_nav) {
		$this->error_nav = $error_nav;
	}

	public function set_form_creator($creator) {
		$this->creator = $creator;
	}

	/**
	 * adds extra access checks, dependent on page state
	 */
	function page_inc_check_access($page) {
		$this->access->check_access("ADMIN");
	}

	function page_inc_execute_action($page, $action) {

		switch($action) {
			case "edit":
				break;
			case "add":
				break;
			default:
				$this->alerter->add_alert("unknown action: $action");
				break;
		}
	}

	/**
	 * execute page logic
	 */
	//Todo: Clean up huge frackin' function
	function page_inc_execute($page) {
		global $CONFIG;
		$THISDIR = $page->directory_tree[$page->dir_depth-1];

		$page->content['title'] = "Administrator panel > access rights";

		if ($_POST['submitted']) { 
		
			if ($_POST['rule']) {
				$rule = "ALLOW";
			} else {
				$rule = "DENY";
			}

			if ($_POST['subject'] == "guest") {
				$subject = "GUEST";
			} else if ($_POST['user_id']) {
				$subject = "USER #{$_POST['user_id']} '{$_POST['name']}'";
			} else if ($_POST['usergroup_id']) {
				$subject = "GROUP #{$_POST['usergroup_id']} '{$_POST['description']}'";
			} else if ($_POST['ipstring']) {
				$subject = "IP '{$_POST['ipstring']}'";
			} else {
				$this->error_nav->errorpage(9);
				return;
			}

			$rule = "$rule {$_POST['action_id']} in dir #{$_POST['dir_id']} for $subject (rank {$_POST['rank']})";

			if ($_GET['action'] == "add") {
					
				if (!$_POST['confirmed']) {
					$page->content['form'] = $this->creator->confirm("Bent u zeker dat u deze regel wil toevoegen: '$rule'");
				} else if ($_POST['confirmed'] == "YES") {
					// add rule
					$sql = $this->db_access->db_query_insert(
							array(
									'dir_id', 
									'action_id', 
									'user_id', 
									'usergroup_id', 
									'ipstring', 
									'guest', 
									'allow', 
									'rank'), 
							array(
									($_POST['dir_id'] == "ROOT") ? 0 : $_POST['dir_id'], 
									$_POST['action_id'], 
									$_POST['user_id'] ? $_POST['user_id'] : "NULL", 
									$_POST['usergroup_id'] ? $_POST['usergroup_id'] : 0, 
									$_POST['ipstring'] ? $_POST['ipstring'] : "''", 
									($_POST['subject'] == "guest") ? 1 : 0, 
									($_POST['rule'] == "deny") ? 0 : 1, 
									$_POST['rank']), "ACCESS_RULE");
					$this->db_access->db_do_query($sql);
					$this->toolbox->add_log("gebruiker #{$_SESSION['user_id']} voegde volgende regel toe: '$rule'");
					$this->toolbox->endpage("rule added: $sql");
				}
			
			} else if ($_GET['action'] == "edit") {
			
				if ($_POST['delete']) {
					if (!$_POST['confirmed']) {
						$sql = $this->db_access->db_query_select(
								array(
										array(), 
										"ACCESS_RULE.*, MEMBER.name, ACCESS_ACTION.action, USERGROUP.description"), 
								array(
										"((ACCESS_RULE LEFT JOIN ACCESS_ACTION ON ACCESS_RULE.action_id = ACCESS_ACTION.action_id) LEFT JOIN MEMBER ON ACCESS_RULE.user_id = MEMBER.user_id) LEFT JOIN USERGROUP ON ACCESS_RULE.usergroup_id = USERGROUP.usergroup_id"), 
								"access_id = {$page->id}", 
								"action ASC, rank ASC");
						$sqlresult = $this->db_access->db_do_query($sql);
						$oldr = $this->db_access->db_fetch_array($sqlresult);
						if ($oldr['rule']) {
							$oldrule = "ALLOW";
						} else {
							$oldrule = "DENY";
						}
						if ($oldr['guest']) {
							$subject = "GUEST";
						} else if ($oldr['user_id']) {
							$subject = "USER #{$oldr['user_id']} '{$oldr['name']}'";
						} else if ($oldr['usergroup_id']) {
							$subject = "GROUP #{$oldr['usergroup_id']} '{$oldr['description']}'";
						} else if ($oldr['ipstring']) {
							$subject = "IP '{$oldr['ipstring']}'";
						} else {
							errorpage(9);
						}
						$oldrule = "$oldrule {$oldr['action']} in dir #{$oldr['dir_id']} for $subject (rank {$oldr['rank']})";
						$page->content['form'] = $this->creator->confirm(
								"Bent u zeker dat u '$oldrule' wil verwijderen ?");
					} else if ($_POST['confirmed'] == "YES") {
						// delete rule
						$sql = $this->db_access->db_query_delete("ACCESS_RULE", "access_id = {$page->id}");
						$this->db_access->db_do_query($sql);
						add_log("gebruiker #{$_SESSION['user_id']} verwijderde deze regel: '$rule'");
						$this->item_functions->endpage("rule deleted");
					}
			
				} else {
					if (!$_POST['confirmed']) {
						$sql = $this->db_access->db_query_select(array(array(), "ACCESS_RULE.*, MEMBER.name, ACCESS_ACTION.action, USERGROUP.description"), array("((ACCESS_RULE LEFT JOIN ACCESS_ACTION ON ACCESS_RULE.action_id = ACCESS_ACTION.action_id) LEFT JOIN MEMBER ON ACCESS_RULE.user_id = MEMBER.user_id) LEFT JOIN USERGROUP ON ACCESS_RULE.usergroup_id = USERGROUP.usergroup_id"), "access_id = {$page->id}", "action ASC, rank ASC");
						$sqlresult = $this->db_access->db_do_query($sql);
						$oldr = $this->db_access->db_fetch_array($sqlresult);
						if ($oldr['rule']) {
							$oldrule = "ALLOW";
						} else {
							$oldrule = "DENY"; 
						}

						if ($oldr['guest']) {
							$subject = "GUEST";
						} else if ($oldr['user_id']) {
							$subject = "USER #{$oldr['user_id']} '{$oldr['name']}'";
						} else if ($oldr['usergroup_id']) {
							$subject = "GROUP #{$oldr['usergroup_id']} '{$oldr['description']}'";
						} else if ($oldr['ipstring']) {
							$subject = "IP '{$oldr['ipstring']}'";
						} else {
							errorpage(9);
						}
						$oldrule = "$oldrule {$oldr['action']} in dir #{$oldr['dir_id']} for $subject (rank {$oldr['rank']})";
						$page->content['form'] = $this->creator->confirm(
								"Bent u zeker dat u '$oldrule' wil veranderen in '$rule' ?");
					} else if ($_POST['confirmed'] == "YES") {
						// edit rule
						$sql = $this->db_access->db_query_update(
								array('dir_id', 
										'action_id', 
										'user_id', 
										'usergroup_id', 
										'ipstring', 
										'guest', 
										'allow', 
										'rank'), 
								array(($_POST['dir_id'] == "ROOT") ? 0 : $_POST['dir_id'],
										$_POST['action_id'], 
										$_POST['user_id'] ? $_POST['user_id'] : "NULL", 
										$_POST['usergroup_id'] ? $_POST['usergroup_id'] : 0, 
										$_POST['ipstring'] ? $_POST['ipstring'] : "''", 
										($_POST['subject'] == "guest") ? 1 : 0, 
										($_POST['rule'] == "deny") ? 0 : 1, 
										$_POST['rank']), 
										"ACCESS_RULE", 
										"access_id = {$page->id}");
						$this->db_access->db_do_query($sql);
						$this->toolbox->add_log("gebruiker #{$_SESSION['user_id']} paste deze regel aan: '$rule'");
						$this->toolbox->endpage($page, "rule edited: $sql");
					}
				}
			}
		} else {
			$inputs = array();

			if ($_GET['action'] == "edit") {
				$sql = $this->db_access->db_query_select(
						array(
								array(), 
								"ACCESS_RULE.*, MEMBER.name, ACCESS_ACTION.action, USERGROUP.description"), array("((ACCESS_RULE LEFT JOIN ACCESS_ACTION ON ACCESS_RULE.action_id = ACCESS_ACTION.action_id) LEFT JOIN MEMBER ON ACCESS_RULE.user_id = MEMBER.user_id) LEFT JOIN USERGROUP ON ACCESS_RULE.usergroup_id = USERGROUP.usergroup_id"), 
						"access_id = {$page->id}", 
						"action ASC, rank ASC");
				$sqlresult = $this->db_access->db_do_query($sql);
				$rule = $this->db_access->db_fetch_array($sqlresult);
			}

			if (($_GET['action'] == "add") or ($_GET['action'] == "edit")) {
				$inputs[] = $this->creator->input_hidden("access_id", $rule['access_id']);
			
				$inputs[] = $this->creator->input_select("regel", "rule", array('allow','deny'), array('allow', 'deny'), "", $rule['rule'] ? "allow" : "deny");

				$kv = $this->generate_dirlist(0, 1, array('ROOT'), array('root'), $page->menu);
				$inputs[] = $this->creator->input_select("directory", "dir_id", $kv['keys'], $kv['values'], "", $rule['dir_id']);

				$kv = $this->toolbox->get_keys_and_values("action_id", "action", "ACCESS_ACTION", 1, "action ASC");
				$inputs[] = $this->creator->input_select("actie", "action_id", $kv['keys'], $kv['values'], "", $rule['action_id']);
				
				if (($_POST['subject'] == "guest") or $rule['guest']) {
					$subject = "guest";
				} else if (($_POST['subject'] == "user") or $rule['user_id']) {
					$subject = "user";
					$user = $rule['user_id'];
				} else if (($_POST['subject'] == "usergroup") or $rule['usergroup_id']) {
					$subject = "usergroup";
					$usergroup = $rule['usergroup_id'];
				} else if (($_POST['subject'] == "ipstring") or $rule['ipstring']) {
					$subject = "ipstring";
					$ipstring = $rule['ipstring'];
				}

				$inputs[] = $creator->input_select("subject", 
						"subject", 
						array('guest', 
								'user', 
								'usergroup', 
								'ipstring'), 
						array('guest', 
								'user', 
								'usergroup', 
								'ipstring'), 
						"", 
						$subject, 
						"document.accessform.submit()"); //TODO: remove javascript
				switch ($subject) {
					case 'guest':
						$inputs[] = $this->creator->input_hidden("guest", "guest", "guest", 10, 10, "", 1);
						break;
					case 'user':
						$kv = get_keys_and_values("user_id", "nick", "MEMBER", 1, "nick ASC");
						$inputs[] = $this->creator->input_select("gebruiker", "user_id", $kv['keys'], $kv['values'], "", $user);
						break;
					case 'usergroup':
						$kv = get_keys_and_values("usergroup_id", "description", "USERGROUP", 1, "usergroup_id ASC");
						$inputs[] = $this->creator->input_select("groep", "usergroup_id", $kv['keys'], $kv['values'], "", $usergroup);
						break;
					case 'ipstring':
						$inputs[] = $creator->input_field("ipstring", "ipstring", $ipstring, 40, 40);
						break;
				}
				$inputs[] = $this->creator->input_field("rank", "rank", $rule['rank'], 1, 1);

				if ($_GET['action'] == "edit") {
					$inputs[] = $this->creator->input_checkbox("delete this rule", "delete");
				}
			}

			$page->content['form'] = $this->creator->create("accessform", array_reverse($inputs));	
		}
		
		$sql = $this->db_access->db_query_select(
				array(
						array(), 
						"ACCESS_RULE.*, MEMBER.name, ACCESS_ACTION.action, USERGROUP.description"), 
				array(
						"((ACCESS_RULE LEFT JOIN ACCESS_ACTION ON ACCESS_RULE.action_id = ACCESS_ACTION.action_id) LEFT JOIN MEMBER ON ACCESS_RULE.user_id = MEMBER.user_id) LEFT JOIN USERGROUP ON ACCESS_RULE.usergroup_id = USERGROUP.usergroup_id"), 
				1, 
				"action ASC, rank ASC");
		$sqlresult = $this->db_access->db_do_query($sql);
		$rows = array();
		while ($r = $this->db_access->db_fetch_array($sqlresult)) {
			if ($r['allow']) {
				$rule = "ALLOW";
			} else {
				$rule = "DENY";
			}
			if ($r['guest']) {
				$subject = "GUEST";
			} else if ($r['user_id']) {
				$subject = "USER #{$r['user_id']} '{$r['name']}'";
			} else if ($r['usergroup_id']) {
				$subject = "GROUP #{$r['usergroup_id']} '{$r['description']}'";
			} else if ($r['ipstring']) {
				$subject = "IP '{$r['ipstring']}'";
			} else {
				$subject = "unknown ????";
			}
			$actions = "<a href={$page->dir_path}/{$r['access_id']}.access?action=edit>edit</a>";
			if ($r['dir_id']) {
				$sql = $this->db_access->db_query_select(array(array('menuname')), array('DIRECTORY'), "dir_id = {$r['dir_id']}");
				$dir = $this->db_access->db_fetch_array(
						$this->db_access->db_do_query($sql));
				$dir = $dir['menuname'] ? $dir['menuname'] : "-";
			} else {
				$dir = "root";
			}
			$row = array($rule, $r['action'], $dir, $subject, $r['rank'], $actions);
			array_push($rows, $row);
		}
		$headers = array("rule", "action", "directory", "subject", "rank", " ");
		$aligns = array("left", "left", "left", "left", "center", "left");
		$widths = array(70, 100, 100, 300, 30, "*");
			
		$page->content['actable'] = array('headers' => $headers, 'rows' => $rows, 'widths' => $widths, 'aligns' => $aligns);
		
		$this->toolbox->add_action($page, "add_access", "url-action", "add");
	}

	/**
	 * dress up page content using skin stuff
	 */
	function page_inc_dress($page) {
		if ($_GET['action'] == "edit" or $_GET['action'] == "add") {
			print_form($page, $page->content['form']);
		}
		print_table($page, $page->content['actable']);
	}

	function generate_dirlist($parent, $level, $keys, $vals, $menu) {
		$rank = 0;	
		$space = "";
		for ($i = 0; $i < $level; $i++) {
			$space .= "&nbsp;&nbsp;&nbsp;&nbsp;";
		}
		while ($id = @array_shift($menu[$parent]['children'])) {
			array_push($keys, $id);
			array_push($vals, $space . $menu[$id]["menuname"]);
			$kv = $this->generate_dirlist($id, ($level+1), $keys, $vals, $menu);
			$keys = $kv['keys'];
			$vals = $kv['values'];
		}
		return array('keys' => $keys, 'values' => $vals);
	}
}

?>
